package avicit.bdp.dms.tdm.service;

import avicit.bdp.common.service.service.InsertSysExcelImportLogService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.common.utils.ConfigUtils;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.core.poi.util.csv.ExcelUtils;
import avicit.bdp.core.poi.util.csv.style.ExcelExportTitleStyle;
import avicit.bdp.dms.tdm.dao.BdpAssetCatalogDAO;
import avicit.bdp.dms.tdm.dto.BdpAssetCatalogDTO;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.commons.utils.PojoUtil;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.domain.VueNode;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.exception.DaoException;
import avicit.platform6.core.mybatis.pagehelper.PageHelper;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryReqBean;
import avicit.platform6.core.rest.msg.QueryRespBean;
import avicit.platform6.modules.system.syslog.service.SysLogUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import com.github.pagehelper.Page;

import java.io.IOException;
import java.util.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * 数据资产数据目录Service
 */
@Service
public class BdpAssetCatalogService {

    private static final Logger logger = LoggerFactory.getLogger(BdpAssetCatalogService.class);

    List<BdpAssetCatalogDTO> dtoList = new ArrayList<>();

    @Autowired
    private BdpAssetCatalogDAO bdpAssetCatalogDAO;

    @Resource
    private InsertSysExcelImportLogService insertSysExcelImportLog;

    /**
     * 按照父id查询数据
     *
     * @param parentId    父节点ID
     * @param level       树等级
     * @param orgIdentity 组织id
     * @return List<VueNode>
     */
    @Transactional(readOnly = true)
    public List<VueNode> getTreeByParentId(String parentId, int level, String orgIdentity) {
        List<VueNode> tree = new ArrayList<>();
        level--;
        List<BdpAssetCatalogDTO> childrenList = findChildrenById(parentId, orgIdentity);
        for (BdpAssetCatalogDTO dto : childrenList) {
            VueNode node = transToTreeNodeData(dto);
            if ("N".equals(dto.getTreeLeaf()) && level > 0) {
                node.setChildren(this.getTreeByParentId(dto.getId(), level, dto.getOrgIdentity()));
            } else {
                // 如果是Y的话就是根节点
                node.setChildren(new ArrayList<>());
            }
            tree.add(node);
        }
        return tree;
    }

    /**
     * 按照父id查询数据（获取有效的数据）
     *
     * @param parentId    父节点ID
     * @param level       树等级
     * @param orgIdentity 组织id
     * @return List<VueNode>
     */
    @Transactional(readOnly = true)
    public List<VueNode> getValidTreeByParentId(String parentId, int level, String orgIdentity) {
        List<VueNode> tree = new ArrayList<>();
        level--;
        List<BdpAssetCatalogDTO> childrenList = findValidChildrenById(parentId, orgIdentity);
        for (BdpAssetCatalogDTO dto : childrenList) {
            VueNode node = transToTreeNodeData(dto);
            if ("N".equals(dto.getTreeLeaf()) && level > 0) {
                node.setChildren(this.getValidTreeByParentId(dto.getId(), level, dto.getOrgIdentity()));
            } else {
                // 如果是Y的话就是根节点
                node.setChildren(new ArrayList<>());
            }
            tree.add(node);
        }
        return tree;
    }

    /**
     * 按条件分页查询
     *
     * @param queryReqBean 查询条件
     * @param orgIdentity  组织id
     * @param wordSecret   文档密级
     * @param orderBy      排序
     */
    @Transactional(readOnly = true)
    public QueryRespBean<BdpAssetCatalogDTO> searchByPage(
            QueryReqBean<BdpAssetCatalogDTO> queryReqBean,
            String orgIdentity,
            String wordSecret,
            String orderBy) {

        QueryRespBean<BdpAssetCatalogDTO> queryRespBean = new QueryRespBean<>();
        try {
            PageHelper.startPage(queryReqBean.getPageParameter());
            BdpAssetCatalogDTO searchParams = queryReqBean.getSearchParams();
            Page<BdpAssetCatalogDTO> dataList =
                    bdpAssetCatalogDAO.searchByPage(
                            searchParams, orgIdentity, wordSecret, orderBy, queryReqBean.getKeyWord());
            queryRespBean.setResult(dataList);
            BdpLogUtil.log4Query(queryRespBean);
            return queryRespBean;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BusinessException("查询失败");
        }
    }

    /**
     * 按照父id查询数据（获取有效的数据并且授权后的数据） -构建树
     *
     * @return List<VueNode>
     */
    @Transactional(readOnly = true)
    public List<VueNode> getTreeAuthValidTree() {
        List<BdpAssetCatalogDTO> list = bdpAssetCatalogDAO.searchCatalogList(ThreadContextHelper.getOrgId(), ThreadContextHelper.getWordSecret());
        BdpAssetCatalogDTO parent = bdpAssetCatalogDAO.getParent();
        boolean parentFlag = false;
        if (CollectionUtils.isNotEmpty(list)) {
            for (BdpAssetCatalogDTO bdpAssetCatalogDTO : list) {
                if ("-1".equals(bdpAssetCatalogDTO.getParentId())){
                    parentFlag = true;
                    break;
                }
            }
            if (!parentFlag){
                list.add(parent);
            }
        }
        return createTreeData(list);
    }


    /**
     * 组建树形结构
     *
     * @param entityNodes 节点集合
     * @return List<VueNode>
     */
    private List<VueNode> createTreeData(List<BdpAssetCatalogDTO> entityNodes) {
        List<VueNode> list = transToTreeNodeData(entityNodes);
        List<VueNode> tree = new ArrayList<>();
        for (VueNode vueNode : list) {
            // 找到根节点
            if ("-1".equals(vueNode.getParentId())) {
                tree.add(vueNode);
            }
            List<VueNode> children = new ArrayList<>();
            // 再次遍历list，找到子节点
            for (VueNode node : list) {
                if (node.getParentId().equals(vueNode.getId())) {
                    children.add(node);
                }
            }
            vueNode.setChildren(children);
            if (children.isEmpty()) {
                vueNode.setIsLeaf(true);
            }
        }
        return tree;
    }

    /**
     * 将实体类集合转化成VueNode格式
     *
     * @param entityNodes 实体类节点集合
     * @return List<VueNode>
     */
    private List<VueNode> transToTreeNodeData(List<BdpAssetCatalogDTO> entityNodes) {
        List<VueNode> vueNodes = new ArrayList<>();
        for (BdpAssetCatalogDTO entityNode : entityNodes) {
            VueNode vueNode = transToTreeNodeData(entityNode);
            vueNodes.add(vueNode);
        }
        return vueNodes;
    }

    /**
     * 将实体类转化成VueNode格式
     *
     * @param entityNode 实体类节点对象
     * @return List<VueNode>
     */
    private VueNode transToTreeNodeData(BdpAssetCatalogDTO entityNode) {
        VueNode vueNode = new VueNode();
        vueNode.setId(entityNode.getId());
        vueNode.setKey(entityNode.getId());
        vueNode.setTitle(entityNode.getClassifyName() == null ? "" : entityNode.getClassifyName());
        vueNode.setSelectable(true);
        vueNode.setDisabled(false);
        vueNode.setDisableCheckbox(false);
        vueNode.setParentId(entityNode.getParentId());
        vueNode.setAttributes(entityNode);
        vueNode.setIsLeaf("Y".equals(entityNode.getTreeLeaf()));
        return vueNode;
    }

    /**
     * 通过主键查询单条记录
     *
     * @param id 主键id
     */
    @Transactional(readOnly = true)
    public BdpAssetCatalogDTO queryById(String id) {
        try {
            BdpAssetCatalogDTO dto = bdpAssetCatalogDAO.findById(id);
            // 记录日志
            if (dto != null) {
                SysLogUtil.log4Query(dto);
            }
            return dto;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BusinessException("通过主键查询单条记录失败");
        }
    }

    /**
     * 按id查询展开树
     *
     * @param id id
     * @return VueNode
     */
    public List<VueNode> expandById(String id) {
        BdpAssetCatalogDTO dto = bdpAssetCatalogDAO.findById(id);
        if (dto == null) {
            throw new BusinessException("节点不存在");
        }
        List<String> ids = Arrays.asList(dto.getTreePath().split(Constants.SINGLE_SLASH));
        BdpAssetCatalogDTO rootDto = bdpAssetCatalogDAO.findById(ids.get(0));
        VueNode rootVueNode = transToTreeNodeData(rootDto);
        VueNode tempVueNode = rootVueNode;
        for (String tid : ids.subList(1, ids.size())) {
            List<BdpAssetCatalogDTO> dtoList =
                    bdpAssetCatalogDAO.findChildrenById(tempVueNode.getId(), tempVueNode.getOrgIdentity());
            List<VueNode> vueNodeList = transToTreeNodeData(dtoList);
            tempVueNode.setChildren(vueNodeList);
            for (VueNode vueNode : vueNodeList) {
                if (vueNode.getId().equals(tid)) {
                    tempVueNode = vueNode;
                    break;
                }
            }
        }
        return Collections.singletonList(rootVueNode);
    }

    /**
     * 获取新的treeSort值：在最当前层最大值上递增10
     */
    public Long getNewTreeSortByParentId(String parentId) {
        try {
            Long maxTreeSort = bdpAssetCatalogDAO.findMaxTreeSortByParentId(parentId);
            return maxTreeSort == null ? 10L : maxTreeSort + 10L;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BusinessException("获取新的treeSort值失败");
        }
    }

    /**
     * 新增数据
     *
     * @param dto 保存对象
     * @return String
     */
    @Transactional
    public String insert(BdpAssetCatalogDTO dto) {
        try {
            if (StringUtils.isEmpty(dto.getId())) {
                String id = ComUtil.getId();
                dto.setId(id);
            }
            PojoUtil.setSysProperties(dto, PlatformConstant.OpType.insert);
            // 自动计算其他相关属性值
            setTreeProperties(dto, null, PlatformConstant.OpType.insert);
            bdpAssetCatalogDAO.insert(dto);
            // 记录日志
            SysLogUtil.log4Insert(dto);
            return dto.getId();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BusinessException("新增数据失败");
        }
    }

    /**
     * 更新数据
     *
     * @param dto 更新对象
     * @return int
     */
    @Transactional
    public boolean update(BdpAssetCatalogDTO dto) {
        boolean flag = false;
        List<BdpAssetCatalogDTO> updateChildrenList = null;
        BdpAssetCatalogDTO old = bdpAssetCatalogDAO.findById(dto.getId());
        if (isMoveToSelfChildNode(dto, old)) {
            throw new BusinessException("非法移动，不允许将节点移动到自身或者子节点下");
        }
        String oldParentId = old.getParentId();
        String orgIdentity = old.getOrgIdentity();
        if (isUpdateTreeProperties(dto, old)) {
            setTreeProperties(dto, old, PlatformConstant.OpType.update);
            updateChildrenList = updateChildrenTreeProperties(dto, old);
            flag = true;
        }
        int ret = bdpAssetCatalogDAO.updateAll(getUpdateDto(dto));
        if (ret == 0) {
            throw new DaoException("数据失效，请重新更新");
        }
        if (!CollectionUtils.isEmpty(updateChildrenList)) {
            bdpAssetCatalogDAO.batchUpdate(updateChildrenList);
        }
        // 新的父节点变更为非叶子节点
        if (!StringUtils.equals("-1", dto.getParentId())) {
            BdpAssetCatalogDTO parentDTO = bdpAssetCatalogDAO.findById(dto.getParentId());
            parentDTO.setTreeLeaf("N");
            bdpAssetCatalogDAO.updateAll(parentDTO);
        }
        // 判断原节点是否还有子节点，否则改为叶子节点
        List<BdpAssetCatalogDTO> childrenList =
                bdpAssetCatalogDAO.findChildrenById(oldParentId, orgIdentity);
        if (CollectionUtils.isEmpty(childrenList)) {
            BdpAssetCatalogDTO oldParentDTO = bdpAssetCatalogDAO.findById(oldParentId);
            oldParentDTO.setTreeLeaf("Y");
            bdpAssetCatalogDAO.updateAll(oldParentDTO);
        }

        BdpLogUtil.log4Update(dto, old);
        return flag;
    }

    /**
     * 判断是是否移动节点到自身或者子节点下
     *
     * @param dto 更新对象
     * @param old 源对象
     * @return boolean
     */
    private boolean isMoveToSelfChildNode(BdpAssetCatalogDTO dto, BdpAssetCatalogDTO old) {
        if (!dto.getParentId().equals(old.getParentId())) {
            // 判断是否移动到自身下面
            if (dto.getParentId().equals(old.getId())) {
                return true;
            }
            // 判断是否移动到子节点下
            List<BdpAssetCatalogDTO> children = bdpAssetCatalogDAO.findByTreePath(old.getTreePath());
            for (BdpAssetCatalogDTO child : children) {
                if (child.getId().equals(dto.getParentId())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 启用/停用
     *
     * @param assetCatalogDTO 修改对象
     * @return int
     */
    @Transactional
    public int updateDataStatus(BdpAssetCatalogDTO assetCatalogDTO) {
        try {
            // 最终处理的List
            List<BdpAssetCatalogDTO> newList = new ArrayList<>();
            // 本节点
            String newStatus = assetCatalogDTO.getStatus();
            newList.add(assetCatalogDTO);
            // 获取所有的子节点
            List<BdpAssetCatalogDTO> childrenList = this.findChildren(assetCatalogDTO.getId());
            int count = 0;
            if ("0".equals(newStatus)) {

                // "0" 停用
                for (BdpAssetCatalogDTO dto : childrenList) {
                    dto.setStatus(newStatus);
                    newList.add(dto);
                }
                count = bdpAssetCatalogDAO.batchUpdate(newList);
                if (count == 0) {
                    throw new BusinessException("数据失效，请重新更新");
                }
            } else if ("1".equals(newStatus)) {
                dtoList = new ArrayList<>();
                // "1启用"
                // 获取该节点所有的父节点->递归获取
                List<BdpAssetCatalogDTO> dtoList =
                        this.findParent(assetCatalogDTO.getParentId(), ThreadContextHelper.getOrgId());
                dtoList.addAll(childrenList);
                // 处理子节点
                for (BdpAssetCatalogDTO dto : dtoList) {
                    dto.setStatus(newStatus);
                    newList.add(dto);
                }
                count = bdpAssetCatalogDAO.batchUpdate(newList);
                if (count == 0) {
                    throw new BusinessException("数据失效，请重新更新");
                }
            }
            return count;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BusinessException("修改对象失败");
        }
    }

    /**
     * 获取所有的子节点
     *
     * @param id id
     */
    private List<BdpAssetCatalogDTO> findChildren(String id) {
        // 当前节点
        BdpAssetCatalogDTO dto = bdpAssetCatalogDAO.findById(id);
        if (dto == null) {
            throw new BusinessException("数据失效，请重新更新");
        }
        String treePath = dto.getTreePath();
        if (StringUtils.isEmpty(treePath)) {
            throw new BusinessException("树路径错误，更新失败");
        }
        return bdpAssetCatalogDAO.findByTreePath(treePath);
    }

    /**
     * 获取所有的父节点
     *
     * @param parentId    拿父ID查询数据
     * @param orgIdentity org
     */
    private List<BdpAssetCatalogDTO> findParent(String parentId, String orgIdentity) {
        // 获取所有的父节点
        BdpAssetCatalogDTO dto = bdpAssetCatalogDAO.findParentById(parentId, orgIdentity);
        if (dto != null && !"-1".equals(dto.getParentId())) {
            dtoList.add(dto);
            this.findParent(dto.getParentId(), orgIdentity);
        }
        return dtoList;
    }

    /**
     * 内部方法，获取修改的dto对象
     */
    private BdpAssetCatalogDTO getUpdateDto(BdpAssetCatalogDTO dto) {
        BdpAssetCatalogDTO oldDTO = findById(dto.getId());
        if (oldDTO == null) {
            throw new BusinessException("数据不存在");
        }
        // 记录日志
        SysLogUtil.log4Update(dto, oldDTO);
        PojoUtil.setSysProperties(dto, PlatformConstant.OpType.update);
        if (StringUtils.isEmpty(dto.getTreePath())) {
            dto.setTreePath(oldDTO.getTreePath());
        }
        if (dto.getTreeLevel() == null) {
            dto.setTreeLevel(oldDTO.getTreeLevel());
        }
        if (StringUtils.isEmpty(dto.getTreeLeaf())) {
            dto.setTreeLeaf(oldDTO.getTreeLeaf());
        }
        if (StringUtils.isEmpty(dto.getTreeSorts())) {
            dto.setTreeSorts(oldDTO.getTreeSorts());
        }
        PojoUtil.copyProperties(oldDTO, dto, false);
        return oldDTO;
    }

    /**
     * 根据主键删除数据
     *
     * @param id 主键id
     * @return int
     */
    @Transactional
    public int deleteById(String id) throws Exception {
        if (StringUtils.isEmpty(id)) {
            throw new Exception("删除失败！传入的参数主键为null");
        }
        try {
            // 记录日志
            BdpAssetCatalogDTO dto = bdpAssetCatalogDAO.findById(id);
            if (dto == null) {
                throw new BusinessException("当前选中节点已被删除！");
            }
            if (!"Y".equals(dto.getTreeLeaf())) {
                throw new BusinessException("当前选中节点含有子节点，请先删除子节点！");
            }
            SysLogUtil.log4Delete(dto);
            int count = bdpAssetCatalogDAO.deleteById(id);
            setTreeProperties(dto, null, PlatformConstant.OpType.delete);
            return count;
        } catch (Exception e) {
            throw new DaoException(e.getMessage(), e);
        }
    }

    /**
     * 批量删除数据
     *
     * @param ids 逗号分隔的id串
     * @return int
     */
    @Transactional
    public int deleteByIds(String ids) throws Exception {
        int result = 0;
        if (avicit.platform6.commons.utils.StringUtils.isNotEmpty(ids)) {
            for (String id : ids.split(Constants.COMMA)) {
                deleteById(id);
                result++;
            }
        }
        return result;
    }

    /**
     * 日志专用，内部方法，不再记录日志
     *
     * @param id 主键id
     */
    private BdpAssetCatalogDTO findById(String id) {
        return bdpAssetCatalogDAO.findById(id);
    }

    /**
     * 自动计算树形结构其他属性值
     *
     * @param dto 修改后的对象
     * @param old 原对象（更新方法使用）
     */
    private void setTreeProperties(
            BdpAssetCatalogDTO dto, BdpAssetCatalogDTO old, PlatformConstant.OpType opType) {
        // 获取其父级节点
        BdpAssetCatalogDTO parentDTO = findParentTreeById(dto.getParentId());
        // 非初始化根节点情况
        if (parentDTO != null) {
            // 判断操作类型
            switch (opType) {
                case insert: // 新增
                    // 设置当前树路经
                    dto.setTreePath(parentDTO.getTreePath() + Constants.SINGLE_SLASH + dto.getId());
                    // 设置当前树全路径排序
                    Long treeSort = dto.getTreeSort();
                    String treeSorts = String.format("%06d", treeSort);
                    dto.setTreeSorts(parentDTO.getTreeSorts() + Constants.SINGLE_SLASH + treeSorts);
                    // 设置当前是否为叶子节点，新增全部为叶子节点
                    dto.setTreeLeaf("Y");
                    // 设置当前节点级别
                    dto.setTreeLevel(parentDTO.getTreeLevel() + 1);
                    // 判断当前父节点是否为叶子节点，如果是，则更改为非叶子节点
                    if ("Y".equals(parentDTO.getTreeLeaf())) {
                        parentDTO.setTreeLeaf("N");
                        bdpAssetCatalogDAO.updateAll(parentDTO);
                    }
                    break;
                case update: // 修改
                    // 主要针对于排序字段的修改
                    if (isUpdateTreeProperties(dto, old)) { // 排序字段被修改，则更改整体排序字段
                        // 当前新的本级排序字段
                        String currentTreeSorts = String.format("%06d", dto.getTreeSort());
                        // 当前新的总体排序字段
                        String newTreeSorts =
                                parentDTO.getTreeSorts() + Constants.SINGLE_SLASH + currentTreeSorts;
                        // 赋值
                        dto.setTreeSorts(newTreeSorts);
                        // 重新生成当前节点tree_path路径
                        String currentTreePath = parentDTO.getTreePath() + Constants.SINGLE_SLASH + dto.getId();
                        Long currentTreeLevel = parentDTO.getTreeLevel() + 1;
                        // 赋值
                        dto.setTreePath(currentTreePath);
                        dto.setTreeLevel(currentTreeLevel);
                    }
                    break;
                case delete: // 删除
                    // 判断当前父节点下还是否有子节点，如果没有，则需要把父节点置为叶子节点
                    List<BdpAssetCatalogDTO> childrenList =
                            findChildrenById(dto.getParentId(), dto.getOrgIdentity());
                    if (CollectionUtils.isEmpty(childrenList)) {
                        parentDTO.setTreeLeaf("Y");
                        bdpAssetCatalogDAO.updateAll(parentDTO);
                    }
                    break;
                default:
                    break;
            }
        } else { // 初始化树根节点
            dto.setTreePath(dto.getId());
            // 设置当前树全路径排序
            Long treeSort = dto.getTreeSort();
            String treeSorts = String.format("%06d", treeSort);
            dto.setTreeSorts(treeSorts);
            // 设置当前是否为叶子节点，新增全部为叶子节点
            if (opType == PlatformConstant.OpType.insert) {
                dto.setTreeLeaf("Y");
            }
            // 设置当前节点级别.
            dto.setTreeLevel(1L);
        }
    }

    /**
     * 查询父节点信息
     *
     * @param parentId 父ID
     */
    public BdpAssetCatalogDTO findParentTreeById(String parentId) {
        try {
            BdpAssetCatalogDTO dto = bdpAssetCatalogDAO.findById(parentId);
            // 记录日志
            if (dto != null) {
                SysLogUtil.log4Query(dto);
            }
            return dto;
        } catch (Exception e) {
            throw new DaoException(e.getMessage(), e);
        }
    }

    private boolean isUpdateTreeProperties(BdpAssetCatalogDTO dto, BdpAssetCatalogDTO old) {
        return !old.getTreeSort().equals(dto.getTreeSort())
                || !old.getParentId().equals(dto.getParentId());
    }

    private List<BdpAssetCatalogDTO> findChildrenById(String id, String orgIdentity) {
        try {
            return bdpAssetCatalogDAO.findChildrenById(id, orgIdentity);
        } catch (Exception e) {
            throw new DaoException(e.getMessage(), e);
        }
    }

    /**
     * 获取有效的数据
     *
     * @param id          id
     * @param orgIdentity 组织标识
     */
    private List<BdpAssetCatalogDTO> findValidChildrenById(String id, String orgIdentity) {
        try {
            return bdpAssetCatalogDAO.findValidChildrenById(id, "1", orgIdentity);
        } catch (Exception e) {
            throw new DaoException(e.getMessage(), e);
        }
    }

    /**
     * 更新下属所有节点的tree_path或者是tree_sorts
     */
    private List<BdpAssetCatalogDTO> updateChildrenTreeProperties(
            BdpAssetCatalogDTO parent, BdpAssetCatalogDTO oldParent) {
        // 原来的排序字段和树路径字段
        String oldTreeSorts = oldParent.getTreeSorts();
        String oldTreePath = oldParent.getTreePath();
        // 现在的排序字段
        String currentTreeSorts = parent.getTreeSorts();
        String currentTreePath = parent.getTreePath();
        // 查找当前节点下的所有子节点
        List<BdpAssetCatalogDTO> list = bdpAssetCatalogDAO.findByTreePath(oldTreePath);
        for (BdpAssetCatalogDTO dto : list) {
            dto.setTreePath(dto.getTreePath().replace(oldTreePath, currentTreePath));
            dto.setTreeSorts(
                    dto.getTreeSorts()
                            .substring(0, oldTreeSorts.length())
                            .replace(oldTreeSorts, currentTreeSorts)
                            + dto.getTreeSorts().substring(oldTreeSorts.length()));
            dto.setTreeLevel((long) dto.getTreePath().split(Constants.SINGLE_SLASH).length);
        }
        return list;
    }

    /**
     * 唯一性校验接口
     *
     * @param queryReqBean 查询条件
     */
    @Transactional(readOnly = true)
    public List<BdpAssetCatalogDTO> uniqueCheck(QueryReqBean<BdpAssetCatalogDTO> queryReqBean) {
        try {
            return bdpAssetCatalogDAO.uniqueCheck(
                    queryReqBean.getSearchParams(),
                    ThreadContextHelper.getOrgId(),
                    ThreadContextHelper.getWordSecret());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BusinessException("查询失败");
        }
    }

    public void downloadTemplate(HttpServletResponse response) throws Exception {
        ExcelUtils excelUtils = new ExcelUtils();
        List<BdpAssetCatalogDTO> dataList = new ArrayList<>();

        BdpAssetCatalogDTO dto = new BdpAssetCatalogDTO();
        dto.setParentClassifyFullName("目录1/目录2/目录3");
        dto.setClassifyName("目录名称");
        dto.setClassifyCode("classify_code");
        dto.setClassifyDes("目录描述");
        dto.setTreeSort(1L);
        dto.setStatus("启用/停用");
        dataList.add(dto);

        // 设置导出参数
        ExportParams params = new ExportParams();
        // 设置excel类型，XSSF代表xlsx，HSSF代表xls
        params.setType(ExcelType.XSSF);
        params.setStyle(ExcelExportTitleStyle.class);
        excelUtils.baseExport(dataList, BdpAssetCatalogDTO.class, "资产目录导入模板", params, response);
    }

    public void export(String parentId, String ids, HttpServletResponse response) {

        ExcelUtils excelUtils = new ExcelUtils();

        try {

            List<String> idList = null;
            if (StringUtils.isNotBlank(ids)) {
                idList = Arrays.asList(ids.split(Constants.COMMA));
            }

            List<BdpAssetCatalogDTO> dataList = bdpAssetCatalogDAO.getList(parentId, idList);
            for (BdpAssetCatalogDTO catalogDTO : dataList) {
                if (StringUtils.isNotBlank(catalogDTO.getTreePath())) {
                    String[] treePath = catalogDTO.getTreePath().split(Constants.SINGLE_SLASH);
                    List<String> parentFullName = new ArrayList<>();
                    for (int i = 1; i < treePath.length - 1; i++) {
                        BdpAssetCatalogDTO byId = this.findById(treePath[i]);
                        if (byId != null) {
                            parentFullName.add(byId.getClassifyName());
                        }
                    }

                    catalogDTO.setParentClassifyFullName(String.join(Constants.SINGLE_SLASH, parentFullName));
                }
            }

            ExportParams params = new ExportParams();
            params.setType(ExcelType.XSSF);
            params.setStyle(ExcelExportTitleStyle.class);
            excelUtils.baseExport(dataList, BdpAssetCatalogDTO.class, "资产目录", params, response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String importAssetCatalog(MultipartFile file) throws Exception {
        CheckParaUtils.checkObjectValidity(file, logger, "参数[file]不能为空");

        int successNum = 0;
        int errorNum = 0;
        List<BdpAssetCatalogDTO> errorList = new ArrayList<>();

        ExcelUtils excelUtils = new ExcelUtils();
        List<BdpAssetCatalogDTO> dataList =
                excelUtils.importExcel(file, 0, 1, false, BdpAssetCatalogDTO.class);
        logger.info("解析excel文件数据成功，数据有[{}]条", dataList.size());

        if (CollectionUtils.isNotEmpty(dataList)) {

            BdpAssetCatalogDTO rootNode = bdpAssetCatalogDAO.getRootNode();

            for (BdpAssetCatalogDTO data : dataList) {

                String classifyName = data.getClassifyName();
                String classifyCode = data.getClassifyCode();
                if (StringUtils.isAnyEmpty(classifyName, classifyCode)) {
                    errorList.add(data);
                    errorNum++;
                    data.setErrorMsg("目录名称或目录编码不能为空");
                    continue;
                }

                BdpAssetCatalogDTO byClassifyName = bdpAssetCatalogDAO.findByClassifyName(classifyName);
                if (byClassifyName != null) {
                    errorList.add(data);
                    errorNum++;
                    data.setErrorMsg("目录名称已存在");
                    continue;
                }

                BdpAssetCatalogDTO byClassifyCode = bdpAssetCatalogDAO.findByClassifyCode(classifyCode);
                if (byClassifyCode != null) {
                    errorList.add(data);
                    errorNum++;
                    data.setErrorMsg("目录编码已存在");
                    continue;
                }

                String id = ComUtil.getId();
                data.setId(id);
                data.setOrgIdentity(ThreadContextHelper.getOrgId());
                data.setCreatedBy(ThreadContextHelper.getUserId());
                data.setLastUpdatedBy(ThreadContextHelper.getUserId());
                data.setCreationDate(new Date());
                data.setLastUpdateDate(new Date());
                data.setVersion(1L);

                if (StringUtils.isEmpty(data.getStatus())) {
                    data.setStatus("0");
                }

                String fullTypeName = data.getParentClassifyFullName();
                if (StringUtils.isNotBlank(fullTypeName)) {
                    String[] fullTypeNameArr = fullTypeName.split(Constants.SINGLE_SLASH);
                    List<BdpAssetCatalogDTO> parentNodes = new ArrayList<>();
                    for (String parentNodeName : fullTypeNameArr) {
                        // 查询父节点数据
                        BdpAssetCatalogDTO parentNode = bdpAssetCatalogDAO.findByClassifyName(parentNodeName);
                        if (parentNode != null) {
                            parentNodes.add(parentNode);
                        }
                    }

                    if (parentNodes.size() < fullTypeNameArr.length) {
                        errorList.add(data);
                        errorNum++;
                        data.setErrorMsg("父节点不存在");
                        continue;
                    }

                    BdpAssetCatalogDTO parentDTO = parentNodes.get(fullTypeNameArr.length - 1);
                    data.setParentId(parentDTO.getId());
                    // 设置当前树路经
                    data.setTreePath(parentDTO.getTreePath() + Constants.SINGLE_SLASH + data.getId());
                    // 设置当前树全路径排序
                    Long treeSort = data.getTreeSort();
                    String treeSorts = String.format("%06d", treeSort);
                    data.setTreeSorts(parentDTO.getTreeSorts() + Constants.SINGLE_SLASH + treeSorts);
                    // 设置当前是否为叶子节点，新增全部为叶子节点
                    data.setTreeLeaf("Y");
                    // 设置当前节点级别
                    data.setTreeLevel(parentDTO.getTreeLevel() + 1);
                    // 判断当前父节点是否为叶子节点，如果是，则更改为非叶子节点
                    if ("Y".equals(parentDTO.getTreeLeaf())) {
                        parentDTO.setTreeLeaf("N");
                        bdpAssetCatalogDAO.updateAll(parentDTO);
                    }

                } else {
                    // 一级节点
                    data.setParentId(rootNode.getId());
                    data.setTreePath(rootNode.getId() + Constants.SINGLE_SLASH + id);
                    data.setTreeLevel(2L);
                    Long treeSort = data.getTreeSort();
                    String treeSorts = String.format("%06d", treeSort);
                    data.setTreeSorts(rootNode.getTreeSorts() + Constants.SINGLE_SLASH + treeSorts);
                    data.setTreeLeaf("Y");
                }

                try {
                    bdpAssetCatalogDAO.insert(data);
                    successNum++;
                } catch (Exception e) {
                    logger.error("导入异常：", e);
                    errorNum++;
                    data.setErrorMsg(e.getMessage());
                    errorList.add(data);
                }
            }

            String errorImportFilePath = "";
            if (CollectionUtils.isNotEmpty(errorList)) {
                // 生成错误信息excel
                // 错误文件存储路径
                String dirPath = ConfigUtils.getInstance().getString("system.data.path") + "errorFile/";
                ExportParams params = new ExportParams();
                params.setType(ExcelType.XSSF);
                params.setStyle(ExcelExportTitleStyle.class);
                errorImportFilePath =
                        excelUtils.exportExcel(
                                errorList,
                                BdpAssetCatalogDTO.class,
                                "AssetCatalogImportError_" + System.currentTimeMillis(),
                                params,
                                dirPath);
                logger.info("errorImportFilePath = {}", errorImportFilePath);
            }

            insertSysExcelImportLog.insertSysExcelImportLog(
                    errorImportFilePath,
                    dataList.size(),
                    successNum,
                    errorNum,
                    "AssetCatalogImport",
                    "bdp_asset_catalog");
        }

        return String.format("总共导入%d条，成功%s条,失败%d条。", dataList.size(), successNum, errorNum);
    }

    public List<Map<String, Object>> getTree() {
        // 顶级节点
        List<Map<String, Object>> list = new ArrayList<>();
        // 子节点数据
        Map<String, List<Map<String, Object>>> map = new HashMap<>();

        List<BdpAssetCatalogDTO> allNodeList = bdpAssetCatalogDAO.getAllTree();
        for (BdpAssetCatalogDTO bdpAssetCatalogDTO : allNodeList) {
            if ("-1".equals(bdpAssetCatalogDTO.getParentId())) {
                Map<String, Object> parentMap = new HashMap<>();
                parentMap.put("id", bdpAssetCatalogDTO.getId());
                parentMap.put("classifyName", bdpAssetCatalogDTO.getClassifyName());
                list.add(parentMap);
            } else {
                if (map.containsKey(bdpAssetCatalogDTO.getParentId())) {
                    Map<String, Object> childMap = new HashMap<>();
                    childMap.put("id", bdpAssetCatalogDTO.getId());
                    childMap.put("classifyName", bdpAssetCatalogDTO.getClassifyName());
                    map.get(bdpAssetCatalogDTO.getParentId()).add(childMap);
                } else {
                    List<Map<String, Object>> catalogList = new ArrayList<>();
                    Map<String, Object> childMap = new HashMap<>();
                    childMap.put("id", bdpAssetCatalogDTO.getId());
                    childMap.put("classifyName", bdpAssetCatalogDTO.getClassifyName());
                    catalogList.add(childMap);
                    map.put(bdpAssetCatalogDTO.getParentId(), catalogList);
                }
            }
        }
        listConvert(list, map);
        return list;
    }

    private void listConvert(List<Map<String, Object>> list, Map<String, List<Map<String, Object>>> map) {
        for (Map<String, Object> bdpAssetCatalogDTO : list) {
            List<Map<String, Object>> assetCatalogList = map.get(bdpAssetCatalogDTO.get("id"));
            if (CollectionUtils.isNotEmpty(assetCatalogList)) {
                listConvert(assetCatalogList, map);
                bdpAssetCatalogDTO.put("children", assetCatalogList);
            } /*else {
        bdpAssetCatalogDTO.put("children",null);
      }*/
        }
    }

}
